﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "SElementUISlate.h"


UENUM(BlueprintType)
enum EElementUIBorederLineType
{
	Solid,
	Dashed,
	Point
};

class ELEMENTUISLATE_API SElementUIBorder : public SElementUISlate
{
public:
SLATE_BEGIN_ARGS(SElementUIBorder) : _HAlign(EHorizontalAlignment::HAlign_Center), _VAlign(EVerticalAlignment::VAlign_Center), _Padding(FMargin(0)), _LineType(EElementUIBorederLineType::Solid), _LineColor(FLinearColor::Black), _LineThickness(2), _DashedLength(20), _DashedInterval(5), _DashedOffset(0), _FilletRadius(0.f) { }

		SLATE_DEFAULT_SLOT(FArguments, Content)
		SLATE_ARGUMENT(EHorizontalAlignment, HAlign)
		SLATE_ARGUMENT(EVerticalAlignment, VAlign)
		SLATE_ATTRIBUTE(FMargin, Padding)
		SLATE_ARGUMENT(EElementUIBorederLineType, LineType)
		SLATE_ATTRIBUTE(FLinearColor, LineColor)
		SLATE_ARGUMENT(int32, LineThickness)
		SLATE_ARGUMENT(float, DashedLength)
		SLATE_ARGUMENT(float, DashedInterval)
		SLATE_ATTRIBUTE(float, DashedOffset)
		SLATE_ARGUMENT(float, FilletRadius)

	SLATE_END_ARGS()


	void Construct(const FArguments& InArgs);
	virtual FVector2D ComputeDesiredSize(float) const override;
	virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;


	virtual void SetContentPadding(const FMargin& value) override;
	virtual void SetHAlign(EHorizontalAlignment value) override;
	virtual void SetVAlign(EVerticalAlignment value) override;
	virtual void SetContent(TSharedRef<SWidget> InContent) override;

	virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override
	{
		if (!bIsHovered) return FReply::Unhandled();
		return SWidget::OnMouseButtonDown(MyGeometry, MouseEvent);
	}

	virtual FReply OnMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) override
	{
		if (!bIsHovered) return FReply::Unhandled();
		return SWidget::OnMouseButtonDoubleClick(InMyGeometry, InMouseEvent);
	}

	virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override
	{
		if (!bIsHovered) return FReply::Unhandled();
		return SWidget::OnMouseButtonUp(MyGeometry, MouseEvent);
	}

	virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;

	virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override
	{
		if (!bIsHovered) return;
		return SWidget::OnMouseEnter(MyGeometry, MouseEvent);
	}

	virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override
	{
		return SWidget::OnMouseLeave(MouseEvent);
	}

	virtual FCursorReply OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const override;
	virtual TSharedPtr<IToolTip> GetToolTip() override { return (bIsHovered ? SWidget::GetToolTip() : NULL); }

	void SetLineColor(FLinearColor value);
	void SetLineThickness(int32 value);
	void SetLineType(TEnumAsByte<EElementUIBorederLineType> value);
	void SetDashedLength(float value);
	void SetDashedInterval(float value);
	void SetDashedOffset(float value);
	void SetIsLineOnBorder(bool value);
	void SetFilletRadius(float value);

protected:
	int32 DrawLine(FSlateWindowElementList& ElementList, uint32 InLayer, const FPaintGeometry& PaintGeometry, const TArray<FVector2D>& Points, const FWidgetStyle& InWidgetStyle) const;
	int32 DrawBroder(FSlateWindowElementList& ElementList, uint32 InLayer, const FGeometry& AllottedGeometry, const FWidgetStyle& InWidgetStyle) const;
	int32 DrawSingleBorderLine(FSlateWindowElementList& ElementList, uint32 InLayer, const FGeometry& AllottedGeometry, const TArray<FVector2D>& Points, const FWidgetStyle& InWidgetStyle) const;
	int32 DrawSingleFillet(float Angle, int32 XDirector, int32 YDirector, FSlateWindowElementList& ElementList, uint32 InLayer, const FGeometry& AllottedGeometry, const FWidgetStyle& InWidgetStyle) const;
private:
	TArray<FVector2D> LineLerp(FVector2D StartPoint, FVector2D EndPoint, float StartOffset = 0.f) const;
	bool IsPointOnLineSegment(FVector2D StartPoint, FVector2D EndPoint, FVector2D Point) const;
	bool IsPointInside(FVector2D Point, FVector2D BorderSize);
	float GetMagicNumber(float angle) const;
private:
	EElementUIBorederLineType LineType = EElementUIBorederLineType::Solid;
	TAttribute<FLinearColor> LineColor;
	int32 LineThickness = 0;
	float DashedLength = 0;
	float DashedInterval = 0;
	TAttribute<float> DashedOffset;
	bool bIsHovered = false;
	float FilletRadius = 0.f;
};
